package com.ikun.kunpicturebackend.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ikun.kunpicturebackend.domain.Picture;
import com.ikun.kunpicturebackend.domain.Space;
import com.ikun.kunpicturebackend.domain.User;
import com.ikun.kunpicturebackend.exception.BusinessException;
import com.ikun.kunpicturebackend.exception.ErrorCode;
import com.ikun.kunpicturebackend.exception.ThrowUtils;
import com.ikun.kunpicturebackend.model.dto.analyze.*;
import com.ikun.kunpicturebackend.model.enums.UserRoleEnum;
import com.ikun.kunpicturebackend.model.vo.space.analyze.*;
import com.ikun.kunpicturebackend.service.PictureService;
import com.ikun.kunpicturebackend.service.SpaceAnalyzeService;
import com.ikun.kunpicturebackend.service.SpaceService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class SpaceAnalyzeServiceImpl implements SpaceAnalyzeService {

    @Resource
    private SpaceService spaceService;

    @Resource
    private PictureService pictureService;

    /**
     * 检查空间分析权限
     * @param analyzeRequest
     * @param loginUser
     */
    private void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest analyzeRequest, User loginUser) {
        if (analyzeRequest.isQueryAll() || analyzeRequest.isQueryPublic()) {
            // 分析全空间/公共图库，需要管理员权限
            ThrowUtils.throwIf(!UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()),
                    ErrorCode.NO_AUTH_ERROR, "需要管理员权限");
        } else {
            // 分析个人空间
            ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
            Long spaceId = analyzeRequest.getSpaceId();
            ThrowUtils.throwIf(spaceId == null || spaceId <= 0, ErrorCode.PARAMS_ERROR);
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
            spaceService.checkSpaceAuth(loginUser, space);
        }
    }

    /**
     * 根据查询范围补充查询条件wrapper
     * @param spaceAnalyzeRequest
     * @param queryWrapper
     */
    private static void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper) {
        if (spaceAnalyzeRequest.isQueryAll()) {
            return;
        } else if (spaceAnalyzeRequest.isQueryPublic()) {
            queryWrapper.isNull("spaceId");
        } else {
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(spaceId == null, ErrorCode.PARAMS_ERROR, "未指定空间id");
            queryWrapper.eq("spaceId", spaceId);
        }
    }

    @Override
    public SpaceUsageAnalyzeResponse getSpaceUsageAnalyze(SpaceUsageAnalyzeRequest analyzeRequest, User loginUser) {
        ThrowUtils.throwIf(analyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 权限检查
        checkSpaceAnalyzeAuth(analyzeRequest, loginUser);
        // 构造wrapper
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(analyzeRequest, queryWrapper);

        if (analyzeRequest.isQueryAll() || analyzeRequest.isQueryPublic()) {

            // 指定查询字段
            queryWrapper.select("picSize");

            List<Object> pictureObjList = pictureService.getBaseMapper().selectObjs(queryWrapper);
            // 已使用的空间大小(图片所占空间)
            long usedSize = pictureObjList.stream().mapToLong(value -> value instanceof Long ? (Long) value : 0).sum();
            // 已使用的数量(图片数量)
            long usedCount = pictureObjList.size();

            // 封装返回结果
            SpaceUsageAnalyzeResponse response = new SpaceUsageAnalyzeResponse();
            response.setUsedSize(usedSize);
            response.setUsedCount(usedCount);
            // 公共图库无上限，无比例
            response.setMaxSize(null);
            response.setMaxCount(null);
            response.setSizeUsageRatio(null);
            response.setCountUsageRatio(null);
            return response;
        } else {
            // 个人空间分析
            // 前面已经校验过了
            Space space = spaceService.getById(analyzeRequest.getSpaceId());

            SpaceUsageAnalyzeResponse response = new SpaceUsageAnalyzeResponse();
            response.setUsedSize(space.getTotalSize());
            response.setMaxSize(space.getMaxSize());
            response.setUsedCount(space.getTotalCount());
            response.setMaxCount(space.getMaxCount());
            // 计算百分比
            double sizeUsageRatio = NumberUtil.round(space.getTotalSize() * 100.0 / space.getMaxSize(), 2).doubleValue();
            double countUsageRatio = NumberUtil.round(space.getTotalCount() * 100.0 / space.getMaxCount(), 2).doubleValue();
            response.setSizeUsageRatio(sizeUsageRatio);
            response.setCountUsageRatio(countUsageRatio);
            return response;
        }
    }

    @Override
    public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest analyzeRequest, User loginUser) {
        ThrowUtils.throwIf(analyzeRequest == null || loginUser == null, ErrorCode.PARAMS_ERROR);
        // 权限校验
        checkSpaceAnalyzeAuth(analyzeRequest, loginUser);

        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(analyzeRequest, queryWrapper);
        // 构造查询信息
        queryWrapper.select("category AS category", "COUNT(*) AS count", "SUM(picSize) AS totalSize")
                .groupBy("category");

        // 查询并转换结果
        return pictureService.getBaseMapper().selectMaps(queryWrapper)
                .stream()
                .map(map -> {
                    String category = map.get("category") != null ? map.get("category").toString() : "未分类";
                    Long count = (Long) map.get("count");
                    Long totalSize = (Long) map.get("totalSize");
                    return new SpaceCategoryAnalyzeResponse(category, count, totalSize);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceTagAnalyzeResponse> getSpaceTagAnalyze(SpaceTagAnalyzeRequest analyzeRequest, User loginUser) {
        ThrowUtils.throwIf(analyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 权限检查
        checkSpaceAnalyzeAuth(analyzeRequest, loginUser);

        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(analyzeRequest, queryWrapper);
        // 查询标签
        queryWrapper.select("tags");
        // 标签（json数组字符串）集合
        List<String> tagsJsonList = pictureService.getBaseMapper().selectObjs(queryWrapper)
                .stream()
                .filter(Objects::nonNull)
                .map(Object::toString)
                .collect(Collectors.toList());

        // 合并所有标签并统计使用次数
        Map<String, Long> tagCountMap = tagsJsonList.stream()
                .flatMap(tagsJson -> JSONUtil.toList(tagsJson, String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

        // 转换为响应对象，按使用次数降序排序
        return tagCountMap.entrySet().stream()
                // 降序排序
                .sorted((e1, e2) -> Long.compare(e2.getValue(), e1.getValue()))
                .map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyze(SpaceSizeAnalyzeRequest analyzeRequest, User loginUser) {
        ThrowUtils.throwIf(analyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(analyzeRequest, loginUser);

        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(analyzeRequest, queryWrapper);
        // 查询图片大小
        queryWrapper.select("picSize");
        List<Long> picSizes = pictureService.getBaseMapper().selectObjs(queryWrapper)
                .stream()
                .map(picSize -> ((Number) picSize).longValue())
                .collect(Collectors.toList());

        // 统计指定范围的图片数量
        LinkedHashMap<String, Long> sizeRanges = picSizes.stream().collect(Collectors.groupingBy(
                picSize -> {
                    if (picSize < 100 * 1024) return "<100KB";
                    else if (picSize < 500 * 1024) return "100KB-500KB";
                    else if (picSize < 1024 * 1024) return "500KB-1MB";
                    else return ">1MB";
                }, LinkedHashMap::new, Collectors.counting()
        ));

        // 转换为响应对象
        return sizeRanges.entrySet().stream()
                .map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalyzeRequest analyzeRequest, User loginUser) {
        ThrowUtils.throwIf(analyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(analyzeRequest, loginUser);

        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(analyzeRequest, queryWrapper);
        Long userId = analyzeRequest.getUserId();
        queryWrapper.eq(userId != null, "userId", userId);

        String timeDimension = analyzeRequest.getTimeDimension();
        // 分析时间维度：每日/每周/每月
        switch (timeDimension) {
            case "day":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m-%d') AS period", "COUNT(*) AS count");
                break;
            case "week":
                queryWrapper.select("YEARWEEK(createTime) AS period", "COUNT(*) AS count");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m') AS period", "COUNT(*) AS count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的时间维度");
        }
        // 分组与排序
        queryWrapper.groupBy("period").orderByAsc("period");

        // 查询结果并且转换响应
        List<Map<String, Object>> results = pictureService.getBaseMapper().selectMaps(queryWrapper);
        return results.stream()
                .map(map -> {
                    String period = map.get("period").toString();
                    Long count = (Long) map.get("count");
                    return new SpaceUserAnalyzeResponse(period, count);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest analyzeRequest, User loginUser) {
        ThrowUtils.throwIf(analyzeRequest == null, ErrorCode.PARAMS_ERROR);

        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "spaceName", "userId", "totalSize")
                .orderByDesc("totalSize")
                .last("LIMIT " + analyzeRequest.getTopN());

        // 查询结果
        return spaceService.list(queryWrapper);
    }


}
